package com.beyondsoft.dtc.mobile.automation.util;

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;

import com.beyondsoft.dtc.mobile.automation.base.GlobalConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class FileUtil {
	private final static Logger logger = LoggerFactory
			.getLogger(FileUtil.class);

	public static boolean writeToFile(String fileName, String context,
			boolean append) {
		if (StringUtil.isEmpty(fileName) || StringUtil.isEmpty(context)) {
			return false;
		}

		RandomAccessFile rndFile = null;
		FileLock fileLock = null;
		File file = null;

		try {
			file = new File(fileName);
			if (!append) {
				file.delete();
			}

			if (!file.exists()) {
				file.createNewFile();
			}

			rndFile = new RandomAccessFile(file, "rwd");
			try {
				fileLock = rndFile.getChannel().lock();
			} catch (Exception e) {
			}

			if (rndFile.length() > 0) {
				rndFile.seek(rndFile.length());
			}

			rndFile.writeBytes(context);
			return true;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fileLock != null) {
				try {
					fileLock.release();
				} catch (IOException e) {
				}
			}

			if (rndFile != null) {
				try {
					rndFile.close();
				} catch (IOException e) {
				}
			}
		}
		return false;
	}

	public static String getFileName(String filePath) {
		if ((filePath != null) && (filePath.length() > 0)) {
			int i = filePath.lastIndexOf('/');
			if ((i > -1) && (i < (filePath.length()))) {
				return filePath.substring(i + 1, filePath.length());
			}
		}
		return filePath;
	}

	/**
	 * download file from remote address.
	 *
	 * @param fileName
	 *            target file where will be cached to local.
	 * @param urlString
	 *            remote url for source file.
	 * @return true success, false failure
	 */

	public static long downloadFile(String fileName, String urlString) {

		if (StringUtil.isEmpty(fileName) || StringUtil.isEmpty(urlString)) {
			return 0;
		}

		byte[] buffer = new byte[1024];
		URL url;
		InputStream is = null;
		int originLength = 0;

		logger.debug("preparing download url [{}], file name [{}]", urlString,
				fileName);
		try {
			url = new URL(urlString);
			if (urlString.toLowerCase().startsWith("https")) {
				SSLContext sc = SSLContext.getInstance("SSL");
				sc.init(null,
						new TrustManager[] { new TrustSSL.TrustAnyTrustManager() },
						new java.security.SecureRandom());
				HttpsURLConnection connection = (HttpsURLConnection) url
						.openConnection();
				connection.setRequestProperty("Accept-Encoding", "identity");
				originLength = connection.getContentLength();

				connection.setSSLSocketFactory(sc.getSocketFactory());
				connection
						.setHostnameVerifier(new TrustSSL.TrustAnyHostnameVerifier());
				connection
						.setReadTimeout(GlobalConstants.DEFAULT_CONNECTION_TIMEOUT);
				is = connection.getInputStream();
			} else {
				URLConnection connection = url.openConnection();
				connection.setRequestProperty("Accept-Encoding", "identity");
				originLength = connection.getContentLength();

				connection
						.setReadTimeout(GlobalConstants.DEFAULT_CONNECTION_TIMEOUT);
				is = connection.getInputStream();
			}
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
		logger.info("download apk originLength:" + originLength);
		long fileSize = 0;
		FileOutputStream fos = null;
		File file = new File(fileName);
		try {
			if (file.exists()) {
				file.delete();
			} else if (file.getParentFile() != null
					&& !file.getParentFile().exists()) {
				file.getParentFile().mkdirs();
			}

			file.createNewFile();
			fos = new FileOutputStream(file);
			int len = 0;
			while ((len = is.read(buffer)) != -1) {
				fos.write(buffer, 0, len);
				fileSize += len;
			}
			logger.info("file downloaded at [{}], size [{}]",
					file.getAbsolutePath(), fileSize);
		} catch (Exception e) {
			file.delete();
			logger.error("download file error {}, {}", e.getMessage(), e);
		} finally {
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
				}
			}
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
				}
			}
		}

		buffer = null;
		System.gc();
		logger.info("download apk finally Length:" + fileSize);
		if (originLength != fileSize) {
			return -1;
		} else {
			return fileSize;
		}
	}

	public static boolean createDirs(String path) {
		if (StringUtil.isEmpty(path)) {
			return false;
		}

		File f = new File(path);
		if (!f.exists()) {
			return f.mkdirs();
		}
		return true;
	}

	public static long copyFile(File src, File dest) {
		FileInputStream fi = null;
		FileOutputStream fo = null;
		FileChannel in = null;
		FileChannel out = null;
		long fileSize = 0;

		try {
			if (dest.exists()) {
				dest.delete();
			}
			dest.createNewFile();

			fi = new FileInputStream(src);
			fo = new FileOutputStream(dest);
			in = fi.getChannel();
			out = fo.getChannel();
			fileSize = in.size();
			in.transferTo(0, fileSize, out);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			closeStream(fo);
			closeStream(fi);
			closeStream(in);
			closeStream(out);
		}
		return fileSize;
	}

	public static boolean deleteDir(File file) {
		try {
			if (file == null || !file.exists()) {
				return false;
			}

			if (!file.isDirectory()) {
				return file.delete();
			}

			File[] subFiles = file.listFiles();
			if (subFiles != null) {
				for (File subFile : subFiles) {
					deleteDir(subFile);
				}
			}
			file.delete();
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	private static void closeStream(Closeable stream) {
		try {
			stream.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		downloadFile(
				"test.apk",
				"https://192.168.16.243/s/apk/4831f4e7-c727-402d-808f-23bc718fa4a0/Y29tLnNzLmFuZHJvaWQuYXJ0aWNsZS5uZXdzXzExMjMwMy5hcGs=");
	}
}
